package com.kitty.mina.session;

import com.kitty.game.role.model.Role;
import com.kitty.common.utils.SpringUtils;
import com.kitty.common.start.GameServer;
import com.kitty.game.server.message.RespServerReboot;
import com.kitty.mina.FireWallConfig;
import com.kitty.mina.cache.DataCache;
import com.kitty.mina.cache.SessionUtils;
import com.kitty.mina.message.MessagePusher;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.IoFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

public enum SessionManager {

    /**
     * 枚举单例
     */
    INSTANCE;

    SessionManager() {
//        Thread thread = new NamedThreadFactory("").newThread(new AnonymousCheck());
//        thread.setDaemon(true);
//        thread.start();
    }

    private class AnonymousCheck implements Runnable {

        @Override
        public void run() {
            for (; ; ) {
                try {
                    long now = System.currentTimeMillis();
                    FireWallConfig config = SpringUtils.getBean(FireWallConfig.class);
                    long aliveTime = config.getAnonymousAliveMilli();
                    List<IoSession> toRemove = new ArrayList<>();
                    for (Map.Entry<Long, IoSession> entry : anonymouSessions.entrySet()) {
                        IoSession session = entry.getValue();
                        if (now - session.getCreationTime() > aliveTime) {
                            toRemove.add(session);
                        }
                    }
                    for (IoSession session : toRemove) {
//                        closeSession(session);
                    }
                    Thread.sleep(100);
                } catch (Exception e) {

                }
            }
        }
    }

    /**
     * distributeKey auto generator
     */
    private AtomicInteger distributeKeyGenerator = new AtomicInteger(1);
    /**
     * key=playerId, value=session
     */
    private ConcurrentMap<Integer, IoSession> player2sessions = new ConcurrentHashMap<>();

    /**
     * 匿名链接
     */
    private ConcurrentMap<Long, IoSession> anonymouSessions = new ConcurrentHashMap<>();

    public void registerSession(int roleId, IoSession session) {
        //biding playeId to session
        session.setAttribute(SessionProperties.PLAYER_ID, roleId);
        this.player2sessions.put(roleId, session);
    }

    public void unRegisterSession(int playerId) {
        this.player2sessions.remove(playerId);
    }

    public void add2Anonymous(IoSession session) {
        this.anonymouSessions.putIfAbsent(session.getId(), session);
    }

    public void removeFromAnonymous(IoSession session) {
        this.anonymouSessions.remove(session.getId());
    }

    /**
     * get session's playerId
     *
     * @param session
     * @return
     */
    public long getPlayerIdBy(IoSession session) {
        if (session != null) {
            if (session.containsAttribute(SessionProperties.PLAYER_ID)) {
                return getSessionAttr(session, SessionProperties.PLAYER_ID, Long.class);
            }
        }
        return 0;
    }

    public IoSession getSessionBy(int playerId) {
        return player2sessions.get(playerId);
    }

    /**
     * get appointed sessionAttr
     */
    @SuppressWarnings("unchecked")
    public <T> T getSessionAttr(IoSession session, AttributeKey attrKey, Class<T> attrType) {
        return (T) session.getAttribute(attrKey);
    }

    public int getNextDistributeKey() {
        return this.distributeKeyGenerator.getAndIncrement();
    }

    public String getRemoteIp(IoSession session) {
        return ((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress();
    }

    public void closeSession(IoSession session) {
        if (session == null) {
            return;
        }
        Role role = SessionUtils.getRoleBySession(session);
        if (role != null) {
            SpringUtils.getRoleService().removeOnline(role);
            SpringUtils.getRoleService().addOffline(role);
        }
        String name = role != null ? role.getName() : "";

        if (session.isConnected() && !session.isClosing()) {
            CloseFuture future = session.closeNow();
            future.addListener(new IoFutureListener<IoFuture>() {
                @Override
                public void operationComplete(IoFuture future) {

                }
            });
        }

        anonymouSessions.remove(session.getId());


    }

    /**
     * 踢所有人下线
     */
    public boolean killAllPlayers() {
        //强制存档
        ConcurrentHashMap<Long, Role> onlineRoles = DataCache.ONLINE_ROLES;
        for (Map.Entry<Long, Role> longRoleEntry : onlineRoles.entrySet()) {
            longRoleEntry.getValue().setOn_line(0);
            longRoleEntry.getValue().save();
        }

        GameServer gameServer = SpringUtils.getBean(GameServer.class);
        Map<Long, IoSession> managedSessions = gameServer.getAcceptor().getManagedSessions();
        for (IoSession session : managedSessions.values()) {
            try {
                MessagePusher.pushMessage(session, new RespServerReboot());
                closeSession(session);
            } catch (Exception e) {

                return false;
            }
        }

        return true;
//        for (Map.Entry<Long, IoSession> entry : player2sessions.entrySet()) {
//            IoSession session = entry.getValue();
//            try {
//                MessagePusher.pushMessage(session, new RespServerReboot());
//                closeSession(session);
//            } catch (Exception e) {
//                LoggerUtils.error("", e);
//            }
//        }
    }


}
